using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FernUniHagen.CompilerExtension.DataStructures;
using FernUniHagen.CompilerExtension.Attributes;
using Roslyn.Compilers;
using Roslyn.Compilers.Common;
using Roslyn.Compilers.CSharp;
using FernUniHagen.CompilerExtension.Functions;

namespace FernUniHagen.CompilerExtension.Converter.Block
{
    public class QueryExpressionConverter : BlockNodeFactory
    {
        /// <summary>
        /// Conversion Rule applies the following:
        /// In Case of Option in query (e.g. from t in b) where b has multiplicity option
        /// 1.find the defining class of b
        /// 2.Let the class inherit from IEnumerable(classtype)
        /// 3.Implement the ienumerable interface in class
        ///     3.a content of this method will be a list which is initialised with (this element)
        ///     3.b the enumerator of this list will be returned
        /// </summary>
        /// <param name="newBlock">TODO:Check if required</param>
        /// <param name="nodeToReplace">Infos about the node which will be replaced</param>
        /// <returns></returns>
        public override List<StatementSyntax> ConvertBlockNode()
        {
            var statementsToAdd = new List<StatementSyntax>();
           
            var identifierName = (IdentifierNameSyntax)NodeToReplaceInBlock.ReferencedNode.DescendantNodes().First(p => p is IdentifierNameSyntax);

            if (identifierName == null) throw new Exception("Could not find Identifier in Linq Statement");

            CommonSyntaxNode decleration = SemanticModel.FindDecleration(identifierName);
            TypeSyntax typeOfDeclaration = null;
            if (decleration is FieldDeclarationSyntax)
                typeOfDeclaration = (TypeSyntax)((FieldDeclarationSyntax)decleration).Declaration.DescendantNodes().First(p => p is TypeSyntax);

            if (decleration is PropertyDeclarationSyntax)
                typeOfDeclaration = ((PropertyDeclarationSyntax)decleration).Type;
            //TODO: Also Properties needs to be added see empty if

            string linqVariable = VariableCreatorService.GetTempVariable();

            var dummyList = Syntax.ParseStatement(string.Format("System.Collections.Generic.List<{0}> {1} = new System.Collections.Generic.List<{0}>() {{ {2} }};" +
                Environment.NewLine,
                typeOfDeclaration.ToString(), linqVariable, identifierName.ToString()));

            var newIdentifier = Syntax.IdentifierName(linqVariable);
            StatementReplacements = new StatementReplacement<CommonSyntaxNode>(identifierName, newIdentifier);
            //StatementReplacements.Add(new StatementReplacement(identifierName, newIdentifier));
            statementsToAdd.AddRange(dummyList);

            return statementsToAdd;

        }

    }
}
